package com.server.common.logistics.yw56;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.*;
import cn.hutool.core.map.MapUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import com.google.gson.reflect.TypeToken;
import com.server.common.code.error.BusinessException;
import com.server.common.code.utils.GsonUtils;
import com.server.common.logistics.base.BaseLogisticsService;
import com.server.common.logistics.enums.LogisticsCompanyEnum;
import com.server.common.logistics.enums.ApiEnum;
import com.server.common.logistics.request.LogisticsRequest;
import com.server.common.logistics.result.CreateOrderResult;
import com.server.common.logistics.result.GetOrderResult;
import com.server.common.logistics.result.GetTrackResult;
import com.server.common.logistics.result.PrintLabelSyncResult;
import com.server.common.logistics.yw56.create.YW56CreateOrderRequest;
import com.server.common.logistics.yw56.create.YW56CreateOrderResponse;
import com.server.common.logistics.yw56.enums.YW56ApiEnum;
import com.server.common.logistics.yw56.get.YW56GetOrderResponse;
import com.server.common.logistics.yw56.printLabel.YW56PrintLabelRequest;
import com.server.common.logistics.yw56.printLabel.YW56PrintLabelResponse;
import com.server.common.logistics.yw56.track.YW56GetTrackRequest;
import com.server.common.logistics.yw56.track.YW56GetTrackResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.*;

@Component
@Slf4j
public class YW56ServiceImpl extends BaseLogisticsService {

    @Resource
    private YW56Config yw56Config;

    @Override
    public   <T> YW56Response<T> baseRequest(ApiEnum apiEnum, Object params){

        String paramsJson = GsonUtils.getGson().toJson(params);

        long time = System.currentTimeMillis();
        Map<String,Object> paramMap = new TreeMap<>();
        paramMap.put("user_id",yw56Config.getClientCode());
        paramMap.put("format","json");
        paramMap.put("method",apiEnum.getMethod());
        paramMap.put("timestamp",time);
        paramMap.put("version","V2.0");
        paramMap.put("data", paramsJson);

        String sign = yw56Config.getToken()+yw56Config.getClientCode()+paramsJson+"json"+apiEnum.getMethod()+time+"V2.0"+yw56Config.getToken();
        sign = DigestUtil.md5Hex(sign).toLowerCase();
        paramMap.put("sign", sign);

        String param = MapUtil.sortJoin(paramMap, "&", "=", true);
        HttpRequest httpRequest = HttpUtil.createPost(yw56Config.getApiUrl() + apiEnum.getApiPath()+"?"+param);

        String body = httpRequest.execute().body();
        return GsonUtils.getGson().fromJson(body,new TypeToken<YW56Response<T>>(){}.getType());
    }

    @Override
    public LogisticsCompanyEnum getLogisticsCompanyEnum() {
        return LogisticsCompanyEnum.TW56;
    }

    @Override
    public CreateOrderResult createOrder(LogisticsRequest createOrderRequest) {
        CreateOrderResult createOrderResult = new CreateOrderResult();

        try {
            if(!(createOrderRequest instanceof YW56CreateOrderRequest)){
                createOrderResult.setErrorMsg("下单参数有误");
                return createOrderResult;
            }

            YW56Response<YW56CreateOrderResponse> yw56Response = baseRequest(YW56ApiEnum.CREATE_ORDER, createOrderRequest);

            if(!yw56Response.responseOk()){
                createOrderResult.setErrorMsg(yw56Response.getMessage());
                return createOrderResult;
            }

            if(yw56Response.dataEmpty()){
                createOrderResult.setErrorMsg("下单失败");
                return createOrderResult;
            }

            YW56CreateOrderResponse data = yw56Response.getData();

            createOrderResult.setThirdOrderId(UUID.randomUUID().toString().replace("-",""));
            createOrderResult.setTrackingNumber(data.getTrackingNumber());
            createOrderResult.setTransferBillNo(data.getTransferBillNo());
        }catch (Exception e){
            log.error("下单失败",e);
            createOrderResult.setErrorMsg("下单失败");
        }

        return createOrderResult;
    }

    @Override
    public GetOrderResult getOrder(LogisticsRequest getOrderRequest) {
        GetOrderResult getOrderResult = new GetOrderResult();

        YW56Response<YW56GetOrderResponse> yw56Response = baseRequest(YW56ApiEnum.GET_ORDER, getOrderRequest);

        if(!yw56Response.responseOk()){
            getOrderResult.setErrorMsg(yw56Response.getMessage());
            return getOrderResult;
        }

        if(yw56Response.dataEmpty()){
            getOrderResult.setErrorMsg("获取订单失败");
            return getOrderResult;
        }

        YW56GetOrderResponse data = yw56Response.getData();
        getOrderResult.setTrackingNumber(data.getTrackingNumber());
        getOrderResult.setTransferBillNo(data.getTransferBillNo());

        return getOrderResult;
    }

    @Override
    public GetTrackResult getTracking(LogisticsRequest getTrackRequest) {
        GetTrackResult getTrackResult = new GetTrackResult();

        try {

            if(!(getTrackRequest instanceof YW56GetTrackRequest)){
                getTrackResult.setErrorMsg("查询参数有误");
                return getTrackResult;
            }
            YW56GetTrackRequest yw56GetTrackRequest = (YW56GetTrackRequest)getTrackRequest;
            HttpRequest httpRequest = HttpUtil.createGet(yw56Config.getTrackUrl() + YW56ApiEnum.GET_TRACK.getApiPath() + "?nums="+ yw56GetTrackRequest.getTrackingNumber());

            String body = httpRequest.execute().body();
            YW56GetTrackResponse yw56GetTrackResponse = GsonUtils.getGson().fromJson(body, YW56GetTrackResponse.class);

            if(0 != yw56GetTrackResponse.getCode()){
                getTrackResult.setErrorMsg(yw56GetTrackResponse.getMessage());
                return getTrackResult;
            }

            List<YW56GetTrackResponse.Result> resultList = yw56GetTrackResponse.getResult();
            if(ObjectUtils.isEmpty(resultList)){
                getTrackResult.setErrorMsg("查询失败");
                return getTrackResult;
            }

            YW56GetTrackResponse.Result result = CollUtil.getFirst(resultList);

            getTrackResult.setTrackingNumber(result.getTrackingNumber());

            List<YW56GetTrackResponse.Result.Checkpoints> checkpointsList = result.getCheckpoints();
            if(ObjectUtils.isEmpty(checkpointsList)){
                getTrackResult.setTackList(new ArrayList<>());
                return getTrackResult;
            }

            //起始时间
            YW56GetTrackResponse.Result.Checkpoints startCheckpoints = CollUtil.getFirst(checkpointsList);
            //最后一个物流时间
            YW56GetTrackResponse.Result.Checkpoints overCheckpoints = CollUtil.getLast(checkpointsList);
            //运输时间
            DateTime startCheckpointsDate = DateUtil.parseDate(startCheckpoints.getTimeStamp()).offset(DateField.HOUR, 8);
            DateTime overCheckpointsDate = DateUtil.parseDate(overCheckpoints.getTimeStamp()).offset(DateField.HOUR, 8);
            long transitDay = DateUtil.between(startCheckpointsDate, overCheckpointsDate, DateUnit.DAY);
            getTrackResult.setTransitDay((int) Math.max(transitDay,0));

            //停留时间
            long stayDay = DateUtil.between(overCheckpointsDate, DateUtil.date(),DateUnit.DAY);
            getTrackResult.setStayDay((int) Math.max(stayDay,0));

            //
            for (YW56GetTrackResponse.Result.Checkpoints checkpoints :checkpointsList){
                GetTrackResult.Tack tack = new GetTrackResult.Tack();
                tack.setTime(checkpoints.getTimeStamp());
                tack.setContent(checkpoints.getMessage());
                tack.setLocation(checkpoints.getLocation());
                tack.setStatusCode(checkpoints.getTrackingStatus());
                getTrackResult.getTackList().add(tack);
            }
        }catch (Exception e){
            log.error("查询失败",e);
            getTrackResult.setErrorMsg("查询失败");
        }

        return getTrackResult;
    }

    @Override
    public PrintLabelSyncResult printLabelSync(LogisticsRequest printLabelSyncRequest) {
        PrintLabelSyncResult printLabelSyncResult = new PrintLabelSyncResult();

        try {
            if(!(printLabelSyncRequest instanceof YW56PrintLabelRequest)){
                printLabelSyncResult.setErrorMsg("打印面单请求参数有误");
                return printLabelSyncResult;
            }

            YW56PrintLabelRequest yw56PrintLabelRequest = (YW56PrintLabelRequest) printLabelSyncRequest;
            yw56PrintLabelRequest.setPrintRemark(1);
            YW56Response<YW56PrintLabelResponse> yw56Response = baseRequest(YW56ApiEnum.PRINT_LABEL, yw56PrintLabelRequest);

            if(!yw56Response.responseOk()){
                printLabelSyncResult.setErrorMsg(yw56Response.getMessage());
                return printLabelSyncResult;
            }

            if(yw56Response.dataEmpty()){
                printLabelSyncResult.setErrorMsg("打印面单失败");
                return printLabelSyncResult;
            }

            YW56PrintLabelResponse data = yw56Response.getData();

            if(!data.getIsSuccess()){
                printLabelSyncResult.setErrorMsg(data.getErrorMsg());
                return printLabelSyncResult;
            }

            String base64String = data.getBase64String();
            byte[] bytes = Base64.decode(base64String);
            printLabelSyncResult.setBytes(bytes);
        }catch (Exception e){
            log.error("打印面单失败",e);
            printLabelSyncResult.setErrorMsg("打印面单失败");
        }
        return printLabelSyncResult;
    }

}
